package com.gitee.wsl.android.ext

//package com.dylanc.longan

import android.Manifest.permission.CALL_PHONE
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.Uri
import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.provider.Settings
import android.webkit.MimeTypeMap
import androidx.annotation.RequiresApi
import androidx.annotation.RequiresPermission
import androidx.core.net.toUri
import androidx.core.os.bundleOf
import com.gitee.wsl.android.ext.ApplicationInit.application
import timber.log.Timber
import java.io.File
import java.io.Serializable


object IntentExt{
    const val DEFAULT_REQUEST_CODE=0


    /**
     * 开启定位设置
     *
     * @return
     */
    @JvmStatic
    val locationIntent: Intent
        get() = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)

    /**
     * 开启蓝牙设置
     *
     * @return
     */
    @JvmStatic
    val bluetoothIntent: Intent
        get() = Intent(Settings.ACTION_BLUETOOTH_SETTINGS)

    /**
     * 开启语言设置
     *
     * @return
     */
    @JvmStatic
    val localeIntent: Intent
        get() = Intent(Settings.ACTION_LOCALE_SETTINGS)

    /**
     * 跳转应用程序列表界面
     *
     * @return
     */
    @JvmStatic
    val appIntent: Intent
        get() = Intent(Settings.ACTION_APPLICATION_SETTINGS)

    /**
     * 跳转到应用程序界面（所有的）
     *
     * @return
     */
    @JvmStatic
    val allAppIntent: Intent
        get() = Intent(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS)

    /**
     * 跳转到应用程序界面（已安装的）
     *
     * @return
     */
    @JvmStatic
    val installedAppIntent: Intent
        get() = Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)


    /**
     * 开启辅助设置
     *
     * @return
     */
    @JvmStatic
    val accessibilityIntent: Intent
        get() = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)

    /**
     * 跳转到搜索设置
     *
     * @return
     */
    @JvmStatic
    val searchIntent: Intent
        get() = Intent(Settings.ACTION_SEARCH_SETTINGS)

    /**
     * 跳转到悬浮窗权限设置
     *
     * @return
     */
    @JvmStatic
    val overlayWindowIntent: Intent
        get() = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
            Uri.parse("package:${AppInfo.packageName}"))

    /**
     * 跳转输入法设置
     *
     * @return
     */
    @JvmStatic
    val inputMethodIntent: Intent
        get() = Intent(Settings.ACTION_INPUT_METHOD_SETTINGS)


    /**
     * 开启存储设置
     *
     * @return
     */
    @JvmStatic
    val storageIntent: Intent
        get() = Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS)
    val storagePermissionIntent: Intent
        @RequiresApi(Build.VERSION_CODES.R)
        get() = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
            data = Uri.fromParts("package", application.packageName, null)
        }



    /**
     * 获取 CATEGORY_LAUNCHER Intent
     * @param packageName 应用包名
     * @param className   class.getCanonicalName()
     * @param isNewTask   是否开启新的任务栈
     * @return [Intent]
     */
    fun getCategoryLauncherIntent(
        packageName: String,
        className: String,
        isNewTask: Boolean
    ): Intent? {
        try {
            val intent = Intent(Intent.ACTION_MAIN)
            intent.addCategory(Intent.CATEGORY_LAUNCHER)
            intent.component = ComponentName(packageName, className)
            if (isNewTask) {
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
            }
            return intent
        } catch (e: java.lang.Exception) {
            Timber.d(e, "getCategoryLauncherIntent")
        }
        return null
    }


    /**
     * 播放视频：本地 / 网络
     *
     * @param url
     * @return
     */
//    @JvmStatic
//    fun getVideoIntent(url: String?): Intent {
//        val intent = Intent(Intent.ACTION_VIEW)
//        val uri: Uri = if (isFileExists(url)) {
//            Uri.fromFile(File(url))
//        } else {
//            Uri.parse(url)
//        }
//        intent.setDataAndType(uri, "video/*")
//        return intent
//    }

    /**
     * 播放网络视频
     *
     * @param url
     * @return
     */
    @JvmStatic
    fun getNetVideoIntent(url: String?): Intent {
        val extension = MimeTypeMap.getFileExtensionFromUrl(url)
        val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
        val intent = Intent(Intent.ACTION_VIEW)
        intent.setDataAndType(Uri.parse(url), mimeType)
        return intent
    }

    /**
     * 播放本地音乐
     *
     * @param filePath
     * @return
     */
    @JvmStatic
    fun getAudioIntent(filePath: String?): Intent {
        val intent = Intent()
        intent.action = Intent.ACTION_VIEW
        val file = File(filePath)
        val uri = Uri.fromFile(file)
        intent.setDataAndType(uri, "audio/*")
        return intent
    }

    /**
     * 打开文件
     * @param file     文件
     * @param dataType 数据类型
     * @return `true` success, `false` fail
     */
    fun openFile(
        file: File,
        dataType: String
    ): Intent {
        val intent = Intent(Intent.ACTION_VIEW)
        intent.addCategory(Intent.CATEGORY_DEFAULT)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 临时授权 ( 必须 )
        intent.setDataAndType(file.toUri(), dataType)
        return intent
    }

    /**
     * 打开文件 ( 指定应用 )
     * @param file        文件
     * @param packageName 应用包名
     * @param className   Activity.class.getCanonicalName()
     * @return `true` success, `false` fail
     */
    fun openFileByApp(
        file: File,
        packageName: String,
        className: String
    ): Intent {
        val intent = Intent()
        intent.addCategory(Intent.CATEGORY_DEFAULT)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        intent.data = file.toUri()
        intent.setClassName(packageName!!, className!!)
        return intent
    }

    /**
     * receiver USB broadcast
     */
    @JvmStatic
    fun registerMountAction(): IntentFilter {
        val intentFilter = IntentFilter()
        intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED)
        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED)
        intentFilter.addDataScheme("file")
        return intentFilter
    }

    /**
     * receiver screen on/off broadcast
     */
    @JvmStatic
    fun registerScreenAction(): IntentFilter {
        val intentFilter = IntentFilter()
        intentFilter.addAction(Intent.ACTION_SCREEN_ON)
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF)
        return intentFilter
    }

    /**
     * receiver package install/uninstall broadcast
     */
    @JvmStatic
    fun registerPackageAction(): IntentFilter {
        val intentFilter = IntentFilter()
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
        intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED)
        intentFilter.addDataScheme("package")
        return intentFilter
    }

    /**
     * receiver network broadcast
     */
    @JvmStatic
    fun registerNetworkStateAction(): IntentFilter {
        val intentFilter = IntentFilter()
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION)
        intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
        return intentFilter
    }

    /**
     * receiver boot broadcast
     */
    @JvmStatic
    fun registerBootAction(): IntentFilter {
        val intentFilter = IntentFilter()
        intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED)
        return intentFilter
    }
}

object IntentAction {
    const val start = "start"
    const val play = "play"
    const val stop = "stop"
    const val resume = "resume"
    const val pause = "pause"
    const val addTimer = "addTimer"
    const val setTimer = "setTimer"
    const val prevParagraph = "prevParagraph"
    const val nextParagraph = "nextParagraph"
    const val upTtsSpeechRate = "upTtsSpeechRate"
    const val adjustProgress = "adjustProgress"
    const val adjustSpeed = "adjustSpeed"
    const val prev = "prev"
    const val next = "next"
    const val moveTo = "moveTo"
    const val init = "init"
    const val remove = "remove"
}

inline fun <reified T> Context.intentOf(vararg pairs: Pair<String, *>): Intent =
    intentOfBundle<T>(bundleOf(*pairs))

inline fun <reified T> Context.intentOfBundle(bundle: Bundle): Intent =
    Intent(this, T::class.java).putExtras(bundle)

/*fun <T> Activity.intentExtras(name: String) = lazy<T?> {
    intent.extras[name]
}

fun <T> Activity.intentExtras(name: String, default: T) = lazy {
    intent.extras[name] ?: default
}

fun <T> Activity.safeIntentExtras(name: String) = lazy<T> {
    checkNotNull(intent.extras[name]) { "No intent value for key \"$name\"" }
}

*/

fun Intent.fillIntentArguments(params: Array<out Pair<String, Any?>>) {
    params.forEach {
        when (val value = it.second) {
            null -> putExtra(it.first, null as java.io.Serializable?)
            is Int -> putExtra(it.first, value)
            is Long -> putExtra(it.first, value)
            is CharSequence -> putExtra(it.first, value)
            is String -> putExtra(it.first, value)
            is Float -> putExtra(it.first, value)
            is Double -> putExtra(it.first, value)
            is Char -> putExtra(it.first, value)
            is Short -> putExtra(it.first, value)
            is Boolean -> putExtra(it.first, value)
            is Serializable -> putExtra(it.first, value)
            is Bundle -> putExtra(it.first, value)
            is Parcelable -> putExtra(it.first, value)
            is Array<*> -> when {
                value.isArrayOf<CharSequence>() -> putExtra(it.first, value)
                value.isArrayOf<String>() -> putExtra(it.first, value)
                value.isArrayOf<Parcelable>() -> putExtra(it.first, value)
                else -> throw IllegalArgumentException("Intent extra ${it.first} has wrong type ${value.javaClass.name}")
            }
            is IntArray -> putExtra(it.first, value)
            is LongArray -> putExtra(it.first, value)
            is FloatArray -> putExtra(it.first, value)
            is DoubleArray -> putExtra(it.first, value)
            is CharArray -> putExtra(it.first, value)
            is ShortArray -> putExtra(it.first, value)
            is BooleanArray -> putExtra(it.first, value)
            else -> throw IllegalArgumentException("Intent extra ${it.first} has wrong type ${value.javaClass.name}")
        }
        //return@forEach
    }
}

@RequiresApi(Build.VERSION_CODES.R)
fun Context.openFilesAccessPermissionSetting(): Boolean = Intent(
    Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
    Uri.parse("package:" + application.packageName)
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).startForActivity(this)

fun Context.openOverlaySetting(): Boolean = Intent(
    Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
    Uri.parse("package:" + application.packageName)
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).startForActivity(this)

fun Context.dial(phoneNumber: String): Boolean =
    Intent(Intent.ACTION_DIAL, Uri.parse("tel:${Uri.encode(phoneNumber)}"))
        .startForActivity(this)

@RequiresPermission(CALL_PHONE)
fun Context.makeCall(phoneNumber: String): Boolean =
    Intent(Intent.ACTION_CALL, Uri.parse("tel:${Uri.encode(phoneNumber)}"))
        .startForActivity(this)

fun Context.sendSMS(phoneNumber: String, content: String): Boolean =
    Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:${Uri.encode(phoneNumber)}"))
        .putExtra("sms_body", content)
        .startForActivity(this)

fun Context.browse(url: String, newTask: Boolean = false): Boolean =
    Intent(Intent.ACTION_VIEW, Uri.parse(url))
        .apply { if (newTask) newTask() }
        .startForActivity(this)

fun Context.email(email: String, subject: String? = null, text: String? = null): Boolean =
    Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
        .putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
        .putExtra(Intent.EXTRA_SUBJECT, subject)
        .putExtra(Intent.EXTRA_TEXT, text)
        .startForActivity(this)

fun Context.email( subject: String? = null, text: String? = null,offerChooser: Boolean = false,receipients: List<String>): Boolean {
    val intent = Intent(Intent.ACTION_SEND)
    intent.type = "message/rfc822"
    intent.putExtra(Intent.EXTRA_EMAIL,receipients.toTypedArray())

    intent.addCategory(Intent.CATEGORY_DEFAULT)

    intent.putExtra(Intent.EXTRA_SUBJECT, subject)
    intent.putExtra(Intent.EXTRA_TEXT, text)

    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    val newIntent=if (offerChooser) Intent.createChooser(intent, null) else intent
    return newIntent.startForActivity(this)
}

fun Context.installAPK(uri: Uri): Boolean =
    Intent(Intent.ACTION_VIEW)
        .setDataAndType(uri, "application/vnd.android.package-archive")
        .newTask()
        .grantReadUriPermission()
        .startForActivity(this)

fun Context.openFile(file: File,dataType: String):Boolean{
    if (!file.exists()) return false
    try {
        startActivity(IntentExt.openFile(file, dataType))
        return true
    } catch (e: java.lang.Exception) {
        Timber.d( e, "openFile")
    }
    return false
}

fun Context.openFileByApp(
    file: File,
    packageName: String,
    className: String
):Boolean{
    if (!file.exists()) return false
    try {
        startActivity(IntentExt.openFileByApp(file, packageName, className))
        return true
    } catch (e: java.lang.Exception) {
        Timber.d( e, "openFile")
    }
    return false
}

/**
 * 打开 PDF 文件
 * @param file 文件
 * @return `true` success, `false` fail
 */
fun Context.openPDFFile(file: File): Boolean {
    return openFile(file, "application/pdf")
}

/**
 * 打开 Word 文件
 * @param file 文件
 * @return `true` success, `false` fail
 */
fun Context.openWordFile(file: File): Boolean {
    return openFile(file, "application/msword")
}

/**
 * 调用 WPS 打开 office 文档
 * @param file 文件
 * @return `true` success, `false` fail
 */
fun Context.openOfficeByWPS(file: File): Boolean {
    val wpsPackage = "cn.wps.moffice_eng" // 普通版与英文版一样
    // String wpsActivity = "cn.wps.moffice.documentmanager.PreStartActivity";
    val wpsActivity2 = "cn.wps.moffice.documentmanager.PreStartActivity2"
    // 打开文件
    return openFileByApp(file, wpsPackage, wpsActivity2)
}

fun Intent.startForActivity(currentActivity:Context): Boolean =
    try {
        currentActivity.startActivity(this)
        true
    } catch (e: Exception) {
        e.printStackTrace()
        false
    }

fun Intent.clearTask(): Intent = addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)

fun Intent.clearTop(): Intent = addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

fun Intent.newDocument(): Intent = addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)

fun Intent.excludeFromRecents(): Intent = addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)

fun Intent.multipleTask(): Intent = addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)

fun Intent.newTask(): Intent = addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

fun Intent.noAnimation(): Intent = addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)

fun Intent.noHistory(): Intent = addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)

fun Intent.singleTop(): Intent = addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)

fun Intent.grantReadUriPermission(): Intent = apply {
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}

fun Context.tryStartActivity(intent: Intent, bundle: Bundle? = null): Boolean {
    return try {
        startActivity(intent, bundle)
        true
    } catch (e: ActivityNotFoundException) {
        false
    } catch (e: SecurityException) {
        false
    }
}